home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AOL File Library: 2,801 to 2,900
/
aol-file-protocol-4400-2801-to-2900.zip
/
AOLDLs
/
C++ Files Library
/
Graphic Gems I, II & III (C_C++)
/
Graphics Gems C Code.sea
/
GemsIII
/
accurate_scan
/
dblfixpoint.c
next >
Wrap
C/C++ Source or Header
|
1992-06-16
|
4KB
|
174 lines
#include <stdio.h>
#include "fixpoint.h"
static int verbose = 0;
/* The dblfixpoint representation is signed magnitude, with
hi is 2n bits of integer (n <= 16)
lo is 2m bits of fraction (m <=16)
number = hi + lo * 2^(-2m)
*/
int fp_dblnegative(dblfixpoint x) { return (x.neg); }
dblfixpoint fp_dblnegate(dblfixpoint x)
{ x.neg = !x.neg; return x; }
dblfixpoint fp_dblmultiply(fixpoint x, fixpoint y)
{
dblfixpoint answer;
unsigned int a, b, c, d;
unsigned int xhi, xlo, yhi, ylo;
xhi = (x<0) ? -fp_integer(x) : fp_integer(x);
yhi = (y<0) ? -fp_integer(y) : fp_integer(y);
xlo = fp_fraction(x);
ylo = fp_fraction(y);
a = xhi * yhi;
b = xhi * ylo;
c = xlo * yhi;
d = xlo * ylo;
a += ((b & HIMASK) >> LOBITS);
a += ((c & HIMASK) >> LOBITS);
b = (b & LOMASK) + (c & LOMASK) + ((d & HIMASK) >> LOBITS);
a += ((b & HIMASK) >> LOBITS);
answer.hi = a;
answer.lo = ((b & LOMASK) << LOBITS) | (d & LOMASK);
answer.neg = 0;
if (((x<0) && (y>0)) || ((x>0) && (y<0))) answer = fp_dblnegate(answer);
return(answer);
}
int fp_dbllessthan(dblfixpoint x, dblfixpoint y)
{
int bothneg, xneg, yneg;
xneg = fp_dblnegative(x);
yneg = fp_dblnegative(y);
bothneg = xneg && yneg;
if (xneg && !yneg) return 1;
if (yneg && !xneg) return 0;
if (bothneg) {
x = fp_dblnegate(x);
y = fp_dblnegate(y);
}
if (x.hi < y.hi) return !bothneg;
if (y.hi < x.hi) return bothneg;
if (x.lo < y.lo) return !bothneg;
return bothneg;
}
fixpoint fp_trunc(dblfixpoint a)
{
int hi = (a.hi << LOBITS);
int lo = (a.lo >> LOBITS);
if ((hi >> LOBITS) != a.hi) {
printf("fp_trunc() Overflow converting hibits 0x%08x to 0x%08x fixpoint in (%d,%d) bits\n", a.hi, hi, HIBITS, LOBITS);
}
if (a.neg)
return (-(hi + lo));
else
return (hi + lo);
}
unsigned int add_with_carry(unsigned int a, unsigned int b,
int carry_in, int *carry_out)
{
int ahi, bhi;
unsigned int answer;
*carry_out = 0;
ahi = (0x80000000 & a) ? 1 : 0; /* Is high bit on? */
bhi = (0x80000000 & b) ? 1 : 0;
a &= 0x7fffffff;
b &= 0x7fffffff;
answer = a + b + carry_in; /* this can't overflow (I think) */
if (answer & 0x80000000) {
if (ahi && bhi) *carry_out = 1; /* Hi bit is on, leave it on */
else if (ahi || bhi) { /* Turn hi bit off, turn on carry */
*carry_out = 1;
answer &= 0x7fffffff;
}
}
else { /* else (if answer high bit is off) */
if (ahi && bhi) *carry_out = 1;
else if (ahi || bhi) answer |= 0x80000000;
}
return(answer);
}
dblfixpoint fp_dbladd(dblfixpoint a, dblfixpoint b)
{
dblfixpoint answer;
if (verbose) printf("\nfpdbladd\n");
if ((a.neg && b.neg) || (!a.neg && !b.neg)) {
int carry;
answer.neg = a.neg;
answer.lo = add_with_carry(a.lo, b.lo, 0, &carry);
if ((answer.lo >> 2*LOBITS) && verbose)
printf(" Lobits overflow by 0x%x (ok)\n", (answer.lo >> 2*LOBITS));
/*This puts lobit overflow into .hi, and removes from .lo */
answer.hi = a.hi + b.hi + (answer.lo >> 2*LOBITS) + carry;
answer.lo &= (LOMASK | (LOMASK << LOBITS));
}
else {
if (a.neg) {
unsigned int tmp;
if (verbose) printf("\tCase: a.neg, b.pos, a<b, swapping\n");
a.neg = 0; b.neg =1;
tmp = a.hi; a.hi = b.hi; b.hi = tmp;
tmp = a.lo; a.lo = b.lo; b.lo = tmp;
}
if (a.hi < b.hi) {
if (a.lo <= b.lo) {
if (verbose) printf("\tCase: a.pos, b.neg, a.hi<b.hi, a.lo<=b.lo \n");
answer.neg = 1;
answer.lo = b.lo - a.lo;
answer.hi = b.hi - a.hi;
}
else {
if (verbose) printf("\tCase: a.pos, b.neg, a.hi<b.hi, a.lo > b.lo \n");
answer.neg = 1;
answer.lo = (b.lo - a.lo) & (LOMASK | (LOMASK << LOBITS));
answer.hi = b.hi - a.hi - 1;
}
}
else if ((a.hi == b.hi) && (a.lo < b.lo)) {
if (verbose) printf("\tCase: a.pos, b.neg, a.hi = b.hi, a.lo < b.lo \n");
answer.neg = 1;
answer.lo = b.lo - a.lo;
answer.hi = 0;
}
else {
if (a.lo >= b.lo) {
if (verbose) printf("\tCase: a.pos, b.neg, a.hi > b.hi, a.lo >= b.lo\n");
answer.neg = 0;
answer.lo = a.lo - b.lo;
answer.hi = a.hi - b.hi;
}
else {
if (verbose) printf("\tCase: a.pos, b.neg, a.hi > b.hi, a.lo < b.lo\n");
answer.neg = 0;
answer.lo = (a.lo - b.lo) & (LOMASK | (LOMASK << LOBITS));
answer.hi = a.hi - b.hi - 1;
}
}
}
return(answer);
}